﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AuthoritExtensibility;
using API = Authorit.API;

namespace VariablesInfo
{
    /// <summary>
    /// Implements the VariablesInfo plug-in
    /// </summary>
    public class PluginManager : IPlugin
    {
		#region Fields (6) 

        /// <summary>
        /// Author-it application context
        /// </summary>
        private API.ApplicationContext appContext;
        /// <summary>
        /// Author-it authentication service
        /// </summary>
        private API.Services.Authentication authService;
        /// <summary>
        /// Instance of the UI for the plug-in
        /// </summary>
        private MainForm pluginForm;
        /// <summary>
        /// Local field for the Author-it proxy
        /// </summary>
        private AitApplicationProxy pluginProxy;
        /// <summary>
        /// Arguments for adding the plug-in to the toolbar
        /// </summary>
        private ToolbarAddArgs toolbarArgs;
        /// <summary>
        /// Author-it variable service
        /// </summary>
        private API.Services.Variable varService;

        private API.Services.ObjectCommon commonService;

		#endregion Fields 

		#region Constructors (1) 

        /// <summary>
        /// Initializes a new instance of the <see cref="PluginManager"/> class.
        /// </summary>
        /// <param name="appProxy">Application proxy supplied by Author-it</param>
        public PluginManager(AitApplicationProxy appProxy)
        {
            pluginProxy = appProxy;  //Set the local app proxy to the one passed in by Author-it
            toolbarArgs = new ToolbarAddArgs();  //Initialize the toolbar arguments
            toolbarArgs.IconImage = VariablesInfo.Properties.Resources.variables16;  //Image for the toolbar button
            toolbarArgs.PluginName = "VariablesInfoPlugin";  //Internal name of the plug-in
            toolbarArgs.TargetButtonName = Properties.Resources.ToolbarButtonName;  //Display text for the toolbar button
            toolbarArgs.TargetForm = TargetForm.MainForm;  //Button will appear on the main form, not the book editor
            toolbarArgs.TargetGroupName = "Show";  //Button group in which the toolbar button will appear
            toolbarArgs.Tooltip = Properties.Resources.ToolbarButtonTooltip;  //Tooltip displayed when the user hovers over the toolbar button
            toolbarArgs.OnClick = toolbarClickHandler;  //Handler for the click event for the toolbar button
            pluginProxy.AddPluginToToolbar(toolbarArgs);  //Add the button to the toolbar
        }

		#endregion Constructors 

		#region Methods (5) 

		// Private Methods (5) 

        /// <summary>
        /// Gets a non-null string value
        /// </summary>
        /// <param name="valueToCheck">String to evaluate</param>
        /// <returns>An empty string if <paramref name="valueToCheck"/> is null; otherwise, the method returns the value of the string</returns>
        private string GetStringValue(string valueToCheck)
        {
            if (String.IsNullOrEmpty(valueToCheck))  //Check to see if the parameter is null
            {
                return String.Empty;  //Return empty string
            }
            return valueToCheck;  //Return the parameter
        }

        /// <summary>
        /// Gets a non-null string value
        /// </summary>
        /// <param name="valueToCheck">Integer to evaluate</param>
        /// <returns>An empty string if <paramref name="valueToCheck"/> is null; otherwise, the method returns the string value of the integer</returns>
        private string GetStringValue(int? valueToCheck)
        {
            if (valueToCheck == null)  //Check to see if the parameter is null
            {
                return String.Empty;  //Return an empty string
            }
            return valueToCheck.ToString();  //Return the string value of the parameter
        }

        /// <summary>
        /// Gets a non-null string value
        /// </summary>
        /// <param name="valueToCheck">Boolean to evaluate</param>
        /// <returns>An empty string if <paramref name="valueToCheck"/> is null; otherwise, the method returns the string value of the Boolean</returns>
        private string GetStringValue(bool? valueToCheck)
        {
            if (valueToCheck == null)  //Check to see if the parameter is null
            {
                return String.Empty;  //Return and empty string
            }
            else
            {
                return valueToCheck.ToString();  //Return the string value of the parameter
            }
        }

        /// <summary>
        /// Formats the variable data into a string array
        /// </summary>
        /// <param name="variable">Variable that contains the data to format</param>
        /// <returns>String array that contains the information about the variable</returns>
        private string[] GetVarInfoSet(API.Dto.Variable variable)
        {
            List<string> infoSet = new List<string>();  //Initialize a list of strings in which to store the variable information
            infoSet.Add(GetStringValue(variable.VariableId));  //Add the ID of the variable
            infoSet.Add(GetStringValue(variable.Name));  //Add the name of the variable
            infoSet.Add(variable.VariableType.ToString());  //Add the type of the variable
            infoSet.Add(GetAssignmentCount(variable).ToString());  //Add the count of assignments
            infoSet.Add(GetStringValue(variable.IsVariantCriteria));  //Add the value that indicates whether the variable is variant criteria
            infoSet.Add(GetStringValue(variable.IsPublishPrompt));  //Add the value that indicates whether the variable is prompted for at publishing
            infoSet.Add(GetStringValue(variable.Value));  //Add the default value for the variable
            StringBuilder lov = new StringBuilder();  //Initialize an instance of StringBuild in which to store the list of values for the variable
            foreach (string lovValue in variable.ListOfValues)  //Loop through the list of values for the variable
            {
                lov.AppendLine(lovValue);  //Add the value to the string, with a new line appended
            }
            infoSet.Add(GetStringValue(lov.ToString()));  //Add the list of values
            infoSet.Add(GetStringValue(variable.ValueObjectId));  //Add the value object ID
            infoSet.Add(GetStringValue(variable.StyleId));  //Add the style ID
            infoSet.Add(GetStringValue(variable.Description));  //Add the variable description
            return infoSet.ToArray<string>();  //Return the variable information
        }

        /// <summary>
        /// Gets the number of objects to which the variable is assigned
        /// </summary>
        /// <param name="variable">Variable to get the assignment count for</param>
        /// <returns>Count of objects that have the variable assigned</returns>
        private int GetAssignmentCount(API.Dto.Variable variable)
        {
            int count = 0;  //Initialize the object count
            API.Dto.ObjectSearchCriteria criterion = new API.Dto.ObjectSearchCriteria();  //Initialize the search criterion
            criterion.Field = API.Dto.ObjectSearchField.VariableAssignment;  //Search for variable assignments
            criterion.Value = variable.Name;  //Search for assignments of the named variable
            List<API.Dto.ObjectSearchCriteria> criteria = new List<API.Dto.ObjectSearchCriteria>();  //Initialize the search criteria list
            criteria.Add(criterion);  //Add the criterion to the list
            List<API.Dto.ObjectBrief> assignedObjects = (List<API.Dto.ObjectBrief>)commonService.Search(criteria, API.Dto.ObjectListSort.ObjectCode, API.Dto.SortDirection.Ascending);  //Search for all objects that have the variable assigned
            count = assignedObjects.Count;  //Get the count of objects in the search results
            return count;  //Return the count
        }

        /// <summary>
        /// Handles the click event for the toolbar button.
        /// </summary>
        /// <param name="sender">Object that initiated the event</param>
        /// <param name="args">Arguments for the event</param>
        private void toolbarClickHandler(object sender, AuthoritEventArgs args)
        {
            appContext = Authorit.API.Utilities.PluginUtility.GetAppContext(args);  //Get the application context for this instance of the plug-in
            authService = appContext.GetServiceInstance<API.Services.Authentication>();  //Initialize the authentication service
            varService = appContext.GetServiceInstance<API.Services.Variable>();  //Initialize the variable service
            commonService = appContext.GetServiceInstance<API.Services.ObjectCommon>();  //Initialize the object common service
            API.Dto.ObjectSearchCriteria foo = new API.Dto.ObjectSearchCriteria();
            API.Dto.LoginResponse response = new API.Dto.LoginResponse();  //Initialize the login response
            bool loggedIn = authService.IsLoggedIn();  //Set the flag that indicates whether the user is logged in
            if (!loggedIn)
            {
                response = authService.Login(appContext.LibrariesConfiguration[0].Alias, args.Username, args.Password);  //If the user is not logged in, then attempt to
                if (response.Result == API.Dto.LoginResult.Success)  //Check for the response result
                {
                    loggedIn = true;  //If logging in was successful, set the flag to true
                }
                else
                {
                    loggedIn = false;  //If logging in failed for any reason, set the flag to false
                }
            }
            if (loggedIn)  //Only attempt to get the info if the user is logged in to the library
            {
                List<API.Dto.Variable> allVariables = (List<API.Dto.Variable>)varService.GetAll();  //Get a list of all the variables in the library
                List<string[]> varInfoData = new List<string[]>();  //Initialize a list in which to store the information about the variables
                foreach (API.Dto.Variable variable in allVariables)  //Loop through the list of variables
                {
                    string[] varInfo = GetVarInfoSet(variable);  //Get a string array that contains the information for the variable
                    varInfoData.Add(varInfo);  //Add the string array to the list of variable information
                }
                pluginForm = new MainForm(varInfoData);  //Initialize the UI for the plug-in
                System.Windows.Forms.DialogResult result = pluginForm.ShowDialog();  //Show the UI
            }
        }

		#endregion Methods 
    }
}